#define MYREV 'A'
/*
 * DISKINFO -- a Turbo 'C' program which will display the current drive
 * parameters for your hard disk(s).  Compiled using version 1.5 of Turbo
 * 'C'.  This program is released into the public domain 8/29/88.  This is
 * NOT a shareware program. It might or might not be supported by the author. 
 *
 * Original code:	8/29/88 D. Bushong This revision:  A  (original) 
 *

Revision history 
========================== 
REV	DATE	BY	Reason for mod / effect obtained 
======= ======= ======= ================================================== 
    A	2/ 3/91 Bushong	Change of address (no functional changes)
    B	 /  / 
    C	 /  / 


*/

#include <bios.h>
#include <mem.h>
#include <conio.h>
#include <dos.h>
#include <process.h>

typedef unsigned char BYTE;
typedef unsigned WORD;

struct table {
    WORD maxcyl;
    BYTE maxhead;
    WORD not_used;
    WORD start_precomp;
    BYTE max_burst;
    BYTE control_byte;
    BYTE more_not_used[3];
    WORD landing_zone;
    BYTE sectors_track;
    BYTE rfu;
};
#if ((sizeof(struct table))!=16)
***Alignment error ! ***
#endif

#if (MYREV=='A')
#define MODBY ""
#else
#define MODBY "Modified 00/00/00 by [yourname]"
#endif

struct diskinfo {
    unsigned which_drive;
    unsigned number_of_drives;
    unsigned max_heads;
    unsigned max_cylinders;
    unsigned max_sectors;
} info;

void hello(void)
{
    clrscr();
    gotoxy(1, 2);
    cprintf("   DISKINFO.... display hard disk information from BIOS and drive table\r\n");
    cprintf("   (%c)   Public domain software from Dave Bushong, Dracut, MA 01826\r\n", MYREV);
    gotoxy(1, 25);
    cprintf("%79s\r\n", MODBY);
}

void get_disk_info(struct diskinfo * disk_data)
{
    unsigned buffer[10];
    disk_data->which_drive |= 0x80;
    if (disk_data->which_drive != 0x80 && disk_data->which_drive != 0x81) {
	memset(disk_data, 0, sizeof(struct diskinfo));
	return;
    }
    biosdisk(8, disk_data->which_drive, 0, 1, 1, 1, buffer);

    disk_data->number_of_drives = buffer[1] & 0x03;
    disk_data->max_heads = ((buffer[1] & 0x0f00) >> 8);
    disk_data->max_cylinders = (((buffer[0] & 0xc0) << 2) + (buffer[0] >> 8));
    disk_data->max_sectors = buffer[0] & 0x3f;
    return;
}

struct table far *tp;

void main(void)
{
    /*
     * this program will show what the BIOS thinks is going on with the
     * disks. 
     */

    int i;
    static char fs[] = {'%', '7', 'u', '\0'};
    lowvideo();
    _AH = 8;
    _DL = 0x80;
    geninterrupt(0x13);
    i = _DL;			/* hard drive count */
    i &= 3;

    hello();

    gotoxy(1, 5);

    if (i == 0) {
	cprintf("The BIOS reports that there are NO hard drives present.\r\n");
	gotoxy(1, 24);
	return;
    }
    gotoxy(15, 5);
    cprintf("BIOS \"GETPARM\" values");
    gotoxy(56, 5);
    cprintf("Drive Table values");
    gotoxy(19, 7);
    cprintf("Drive 0   Drive 1");
    gotoxy(57, 7);
    cprintf("Drive 0   Drive 1");
    gotoxy(3, 9);
    cprintf("Max. Cylinder");
    gotoxy(7, 10);
    cprintf("Max. Head");
    gotoxy(5, 11);
    cprintf("Max. Sector");

    gotoxy(41, 9);
    cprintf("Cylinder count");
    gotoxy(45, 10);
    cprintf("Head count");
    gotoxy(42, 11);
    cprintf("Sectors/track");
    gotoxy(42, 12);
    cprintf("Start precomp");
    gotoxy(42, 13);
    cprintf("Maximum burst");
    gotoxy(43, 14);
    cprintf("Control byte");
    gotoxy(43, 15);
    cprintf("Landing zone");

    gotoxy(5, 18);
    cprintf("Note that some values returned from the BIOS are \"zero-based\"; which");
    gotoxy(5, 19);
    cprintf("means that you would start counting at zero.  The drive table is, instead,");
    gotoxy(5, 20);
    cprintf("a one-based count.  For example, if you have four drive heads, they");
    gotoxy(5, 21);
    cprintf("are numbered zero-one-two-three.  The maximum head value would be three.");
    gotoxy(5, 22);
    cprintf("Heads and cylinders start counting at zero; sector numbers start at one.");
    gotoxy(4, 14);
    cprintf("All values shown are in decimal.");

    info.which_drive = 0;
    get_disk_info(&info);
    tp = (struct table far *) getvect(0x41);

    highvideo();
    gotoxy(19, 9);
    cprintf(fs, info.max_cylinders);
    gotoxy(19, 10);
    cprintf(fs, info.max_heads);
    gotoxy(19, 11);
    cprintf(fs, info.max_sectors);

    gotoxy(57, 9);
    cprintf(fs, tp->maxcyl);
    gotoxy(57, 10);
    cprintf(fs, tp->maxhead);
    gotoxy(57, 11);
    cprintf(fs, tp->sectors_track);
    gotoxy(57, 12);
    cprintf(fs, tp->start_precomp);
    gotoxy(57, 13);
    cprintf(fs, tp->max_burst);
    gotoxy(57, 14);
    cprintf(fs, tp->control_byte);
    gotoxy(57, 15);
    cprintf(fs, tp->landing_zone);
    lowvideo();

    if (i == 1) {
	for (i = 9; i < 12; i++) {
	    gotoxy(33, i);
	    cprintf("N/A");
	}
	for (i = 9; i < 16; i++) {
	    gotoxy(71, i);
	    cprintf("N/A");
	}
	gotoxy(1, 24);
	return;
    }
    highvideo();

    info.which_drive = 1;
    get_disk_info(&info);
    tp = (struct table far *) getvect(0x46);

    gotoxy(29, 9);
    cprintf(fs, info.max_cylinders);
    gotoxy(29, 10);
    cprintf(fs, info.max_heads);
    gotoxy(29, 11);
    cprintf(fs, info.max_sectors);

    gotoxy(67, 9);
    cprintf(fs, tp->maxcyl);
    gotoxy(67, 10);
    cprintf(fs, tp->maxhead);
    gotoxy(67, 11);
    cprintf(fs, tp->sectors_track);
    gotoxy(67, 12);
    cprintf(fs, tp->start_precomp);
    gotoxy(67, 13);
    cprintf(fs, tp->max_burst);
    gotoxy(67, 14);
    cprintf(fs, tp->control_byte);
    gotoxy(67, 15);
    cprintf(fs, tp->landing_zone);
    gotoxy(1, 24);
    lowvideo();
    return;
}
